
	/************************************************************************************************

		@API
		Factory:	jsl.Number

		Constructor:
			obj			Number				(n*)

		Static:
			n				fromLString		(s, locale*)
			n				random				(max*, min*)

		Methods:
			n				round					(d*)
			n				ceil					(d*)
			n				floor					(d*)
			n				limit					(max, min*)

			r				toRadiants		()
			d				toDegrees			()

			i				toInteger			()
			b				isInteger			()
			s				toLString			(locale*)

	*************************************************************************************************/

  //-------------------------------------------------------------------------------
	jsl.Number = function(n) {
		try {
	   	var proto, rv
			//!
      if(arguments.length > 1)	throw jsl.ParamError()//!

			if(arguments.length) {

				if(n instanceof Number)
					if(n.__augmented) return n
					else							rv = n
				else {
					//!
					if(isNaN(n))	throw jsl.ParamError("NaNValue:n")//!
					rv = new Number(n)
				}
			}
			else
				rv = new Number

			proto = jsl.Number.prototype

    	for(var id in proto) rv[id] = proto[id]
    	return rv
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Number.__name 							= "jsl.Number"
	jsl.Number.__native 						= { fromLString: true, random: true, __name: true, __augmented: true }
	jsl.Number.__augmented					= true
	//-------------------------------------------------------------------------------
	jsl.Number.prototype 						= jsl.Object()
	jsl.Number.prototype.__name 		= "jsl.Number"
	jsl.Number.prototype.__native 	= jsl.Object.clone(jsl.Object.__native)
	//-------------------------------------------------------------------------------
	jsl.Number.fromLString	= function(s, locale) {
		try {
			var n, l, re

			//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(s, "s+", "s")
			if(arguments.length === 2)	jsl.validate(locale, "s+", "locale")//!

			jsl.require("locale")

			//!
			if(locale && !jsl.Locale.isDefined(locale))	throw jsl.ParamError("NotDefined:locale")//!

			l = jsl.Locale.get(locale || jsl.Locale.current())

			if(l.n_format) {

				try 			{ n = l.n_format.call({}, s)	}
				catch(e) 	{ throw jsl.ScriptError("BadScript:locale[" + l.id + "\\:d_format]", e)	}
				//!
				if(!jsl.isNumber(n)) 	throw jsl.ParamError("BadReturnType:locale[" + l.id + "\\:d_format]:number")
				if(isNaN(n))					throw jsl.ParamError("NotRecognized:s")//!
			}
			else {

				re = "^\\-?\\d{1,3}(\\" + l.n_sep_zero + "\\d{3})*(\\" + l.n_sep_dec + "\\d+)?$"

				//!
				if(!s.match(re))	throw jsl.ParamError("NotRecognized:s")//!
				n = +s.replace(RegExp("\\" + l.n_sep_zero, "g"), "").replace(l.n_sep_dec, ".")
			}
      return n
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Number.random	= function(max, min) {
		try {
			var m,n
			//!
			if(arguments.length > 2)		throw jsl.ParamError()
			if(arguments.length)				jsl.validate(max, "n", "max")
			if(arguments.length === 2)	jsl.validate(min, "n", "min")//!

			m = max != null ? max : 1
			n = min || 0
			//!
			if(n > m)	throw jsl.ParamError("BadInterval:min > max")//!

      return n + Math.random() * (m - n)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Number.prototype.toRadiants	= function() {
		try {//!
			if(!jsl.isNumber(this))	throw jsl.TypeError("BadMethodCall:Number")
			if(arguments.length)		throw jsl.ParamError()//!
      return this * Math.PI / 180
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Number.prototype.toDegrees = function() {
		try {//!
			if(!jsl.isNumber(this))		throw jsl.TypeError("BadMethodCall:Number")
			if(arguments.length)			throw jsl.ParamError()//!
      return this * 180 / Math.PI
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Number.prototype.round = function(d) {
		try {//!
			if(!jsl.isNumber(this))		throw jsl.TypeError("BadMethodCall:Number")
			if(arguments.length > 1)	throw jsl.ParamError()
			if(arguments.length)			jsl.validate(d, "i+", "d")//!

      return +this.toFixed(d || 0)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Number.prototype.ceil	= function(d) {
		try {
			var n
			//!
			if(!jsl.isNumber(this))		throw jsl.TypeError("BadMethodCall:Number")
			if(arguments.length > 1)	throw jsl.ParamError()
			if(arguments.length)			jsl.validate(d, "i+", "d")//!

			if(d) {
	  		n = Math.pow(10, d)
  			n = Math.ceil(this * n) / n
 			}
			else
				n = Math.ceil(this)

  		return n
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Number.prototype.floor = function(d) {
		try {
			var n
			//!
			if(!jsl.isNumber(this))		throw jsl.TypeError("BadMethodCall:Number")
			if(arguments.length > 1)	throw jsl.ParamError()
			if(arguments.length)			jsl.validate(d, "i+", "d")//!

			if(d) {
	  		n = Math.pow(10, d)
  			n = Math.floor(this * n) / n
 			}
			else
				n = Math.floor(this)

  		return n
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Number.prototype.limit = function(max, min) {
		try {
			var n
			//!
			if(!jsl.isNumber(this))												throw jsl.TypeError("BadMethodCall:Number")
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			if(arguments.length)													jsl.validate(max, "N", "max")
			if(arguments.length === 2)										jsl.validate(min, "N", "min")
			if(min != null && min > max)									throw jsl.ParamError("BadInterval:min > max")//!

			if(this > max)											n = max
			else if(min != null && this < min)	n = min
			else																n = this

			return +n
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Number.prototype.toInteger	= function() {
		try {//!
			if(!jsl.isNumber(this))	throw jsl.TypeError("BadMethodCall:Number")
			if(arguments.length)		throw jsl.ParamError()//!
			return ~~this
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Number.prototype.isInteger	= function() {
		try {//!
			if(!jsl.isNumber(this))	throw jsl.TypeError("BadMethodCall:Number")
			if(arguments.length)		throw jsl.ParamError()//!
			return !(this - ~~this)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Number.prototype.toLString	= function(locale) {
		try {
			var s, i, l

			//!
			if(!jsl.isNumber(this))		throw jsl.TypeError("BadMethodCall:Number")
			if(arguments.length > 1)	throw jsl.ParamError()
			if(arguments.length)			jsl.validate(locale, "s+", "locale")//!

			jsl.require("locale")

			//!
			if(locale && !jsl.Locale.isDefined(locale))	throw jsl.ParamError("NotDefined:locale")//!

			l = jsl.Locale.get(locale || jsl.Locale.current())

			if(l.n_format) {

				try 			{ s = l.n_format.call({}, +this)	}
				catch(e) 	{ throw jsl.ScriptError("BadScript:locale[" + l.id + "\\:d_format]", e)	}

				s += ""

				//!
				if(!jsl.isString(s)) 	throw jsl.ParamError("BadReturnType:	locale[" + l.id + "\\:d_format]:string")
				if(!s)								throw jsl.ParamError("BadReturnValue:	locale[" + l.id + "\\:d_format]:string")//!
			}
			else {
				s = this + ""
				i	= s.indexOf(".")
				s = i !== -1 ? s.slice(0, i) : s
				s = s.split("").reverse().join("")
				s = s.replace(/\d{3}/g, "$&" + l.n_sep_zero)
				s = s.split("").reverse().join("")
				s = i !== -1 ? s + l.n_sep_dec + (this + "").slice(i + 1) : s
			}

			return s
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//Number init
	//-------------------------------------------------------------------------------
	;(function() {
		var prt, Num

		Num = jsl.Number
		prt = Num.prototype

		for(var id in prt) {

			Num.__native[id] = true
			prt.__native[id] = true

			if(typeof prt[id] === "function" && !prt[id].__name) {

				Num[id] = function(n) {
					try {//!
						if(!arguments.length)	throw jsl.ParamError()
						jsl.validate(n, "N", "n")//!

						return arguments.callee.__f.apply(n, Array.prototype.slice.call(arguments, 1))
					}
					catch(e) {
						jsl.throwError(e, this, arguments)
					}
				}

				Num[id].__name	= prt[id].__name = id
				Num[id].__f			= prt[id]
			}
		}
	})()
